package com.netease.xone.widget;

import java.lang.reflect.Method;

import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.ListView;

/**
 * 实现了ScrollableListView内嵌到ScrollView中ScrollableListView能够滚动内部item
 * 同时实现了监听是否滚动到两端
 * @author user
 *
 */
public class ScrollableListView extends ListView {
	private boolean DEBUG = true;
	private String TAG = ScrollableListView.class.getSimpleName();
	private int mTouchSlop;

	public ScrollableListView(Context context) {
		this(context, null);
	}

	public ScrollableListView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public ScrollableListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
        
		final ViewConfiguration configuration = ViewConfiguration.get(context);
        mTouchSlop = configuration.getScaledTouchSlop();
        
		/**
		 * 去掉滑到两头时出现阴影
		 */
		if (Build.VERSION.SDK_INT >= 9) {
			try {
				Method method = ListView.class.getMethod("setOverScrollMode", int.class);
				method.invoke(this, View.OVER_SCROLL_NEVER);
			} catch (Exception e) { 
				e.printStackTrace();
			} 
		}
	}

	private boolean mFirstLayout = true;
	private int mOriginTop = 0;
	private int mOriginBottom = 0;
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (mFirstLayout) {
			mFirstLayout = false;
			if (null == getAdapter() || 0 == getAdapter().getCount()) {
				return;
			}
			Rect rect = new Rect();
			getLocalVisibleRect(rect);
			int []location = new int[2];
			getLocationOnScreen(location);
			if (null != getChildAt(0)) {
				mOriginTop = getChildAt(0).getTop();
			}
			if (null != getChildAt(getChildCount()-1)) {
				mOriginBottom = getChildAt(getChildCount()-1).getBottom();
			}
			
			if (DEBUG) {
				Log.d(TAG, "rect=" + rect.toString());
				Log.d(TAG, "location[0]=" + location[0] + " location[1]=" + location[1]);
				Log.d(TAG, "mOriginTop=" + mOriginTop);
				Log.d(TAG, "mOriginBottom=" + mOriginBottom);
			}
		}
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		
		boolean bRes = false;
		
		do {
			switch ( ev.getAction() & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				if (mTop || mBottom) {
					getParent().requestDisallowInterceptTouchEvent(false);
				} else {
					getParent().requestDisallowInterceptTouchEvent(true);
				}
				break;
			case MotionEvent.ACTION_MOVE:
				break;
			case MotionEvent.ACTION_UP:
				break;
			case MotionEvent.ACTION_CANCEL:
				break;
			default:
				break;
			}
			bRes = super.onInterceptTouchEvent(ev);
		} while(false);
		
		if (DEBUG) {
			switch (ev.getAction() & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				Log.d(TAG, "onInterceptTouchEvent MotionEvent.ACTION_DOWN" + " bRes=" + bRes);
				break;
			case MotionEvent.ACTION_MOVE:
				Log.d(TAG, "onInterceptTouchEvent MotionEvent.ACTION_MOVE" + " bRes=" + bRes);
				break;
			case MotionEvent.ACTION_UP:
				Log.d(TAG, "onInterceptTouchEvent MotionEvent.ACTION_UP" + " bRes=" + bRes);
				break;
			case MotionEvent.ACTION_CANCEL:
				Log.d(TAG, "onInterceptTouchEvent MotionEvent.ACTION_CANCEL" + " bRes=" + bRes);
				break;
			default:
				break;
			}
		}
		return bRes;
	}
	
	private boolean mTop = false;
	private boolean mBottom = false;
	private float mLastMotionY;
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		boolean bRes = false;
		final float y = ev.getY();
		final int firstPosition = getFirstVisiblePosition();
		final int lastPosition = getLastVisiblePosition();
		int top = 0;
		int bottom = 0;
		float dy = 0;
		do {
			if (getChildCount() > 0) {
				top = getChildAt(0).getTop();
				bottom = getChildAt(getChildCount()-1).getBottom();
			}
			
			switch ( ev.getAction() & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				mLastMotionY = y;
				mTop = false;
				mBottom = false;
				break;
			case MotionEvent.ACTION_MOVE:
				dy = mLastMotionY - y;
				/**
				 * 判断ListView是否滚动到顶部
				 */
				if (firstPosition == 0 
						&& dy < -mTouchSlop 
						&& top == mOriginTop) {
					mTop = true;
				/**
				 * 判断ListView是否滚动到底部
				 */
				} else if (lastPosition == getAdapter().getCount()-1 
						&& dy > mTouchSlop 
						&& bottom-top >= mOriginBottom) {
					mBottom = true;
				} else {
					mTop = false;
					mBottom = false;
				}
				break;
			case MotionEvent.ACTION_UP:
				break;
			case MotionEvent.ACTION_CANCEL:
				break;
			default:
				break;
			}
			bRes = super.onTouchEvent(ev);
		} while(false);
		
		if (DEBUG) {
			switch (ev.getAction() & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN:
				Log.d(TAG, "onTouchEvent MotionEvent.ACTION_DOWN" + " bRes=" + bRes);
				break;
			case MotionEvent.ACTION_MOVE:
				Log.d(TAG, "onTouchEvent MotionEvent.ACTION_MOVE" + " bRes=" + bRes);
				Log.d(TAG, "onTouchEvent mTop=" + mTop + " mBottom=" + mBottom);
				break;
			case MotionEvent.ACTION_UP:
				Log.d(TAG, "onTouchEvent MotionEvent.ACTION_UP" + " bRes=" + bRes);
				break;
			case MotionEvent.ACTION_CANCEL:
				Log.d(TAG, "onTouchEvent MotionEvent.ACTION_CANCEL" + " bRes=" + bRes);
				break;
			default:
				break;
			}
		}
		
		if (mTop | mBottom) {
			ev.setAction(MotionEvent.ACTION_DOWN);
			dispatchTouchEvent(ev);
			mLastMotionY = y;
		}
		
		return bRes;
	}
}
